package com.hzjy.api.controller;

import com.alipay.api.internal.util.AlipaySignature;
import com.google.common.collect.Maps;
import com.hzjy.api.service.BqTokenService;
import com.hzjy.api.service.impl.ApiProductServiceImpl;
import com.hzjy.api.service.impl.BqUserServiceImpl;
import com.hzjy.api.service.impl.HzjyServiceChargeServiceImpl;
import com.hzjy.api.service.impl.PayServiceImpl;
import com.hzjy.api.vo.BqLoginUser;
import com.hzjy.api.vo.BqUser;
import com.hzjy.common.config.AlipayConfig;
import com.hzjy.common.config.WXpayConfig;
import com.hzjy.common.core.controller.BaseApiController;
import com.hzjy.common.core.domain.AjaxResult;
import com.hzjy.common.exception.BaseException;
import com.hzjy.common.utils.JSONUtil;
import com.hzjy.common.utils.PageData;
import com.hzjy.common.utils.ServletUtils;
import com.hzjy.common.utils.StringUtils;
import com.hzjy.common.utils.http.HttpUtils;
import com.hzjy.common.utils.wx.WXPayUtil;
import com.hzjy.framework.config.ServerConfig;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 微信支付
 */
@RestController
@RequestMapping("/api/wxPay")
public class ApiPayController extends BaseApiController {
    private static final Logger log = LoggerFactory.getLogger(ApiPayController.class);

    @Autowired
    private BqTokenService bqTokenService;
    @Autowired
    private HzjyServiceChargeServiceImpl hzjyServiceChargeService;
    @Autowired
    private ApiProductServiceImpl apiProductService;
    @Autowired
    private BqUserServiceImpl bqUserService;
    @Autowired
    private PayServiceImpl payService;
    @Autowired
    private ServerConfig serverConfig;

    /**
     * 挂牌/摘牌支付计算金额
     */
    @PostMapping(value = "/countMoney")
    public AjaxResult countMoney(@RequestBody PageData pd) {
        log.info("【挂牌支付计算金额】,args:" + JSONUtil.map2json(pd));
        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        if (loginUser == null) {
            return AjaxResult.error(401, "未登录");
        }
        Long contractId = Long.valueOf(pd.get("contractId").toString());
        return payService.countTradeCost(contractId, loginUser.getBqUser().getUserId().toString());
    }

    /**
     * 微信支付成功回调地址
     */
    @PostMapping(value = "/returnPaySucc")
    public String returnPaySucc(HttpServletRequest request, HttpServletResponse response) {
        log.info("【支付成功回调入口】");
        try {
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            String result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            log.info("【微信支付成功回调结果】:" + JSONUtil.map2json(map));
            if (map.get("result_code").equalsIgnoreCase("SUCCESS")) {
                //返回成功后修改订单状态
                String out_trade_no = map.get("out_trade_no");
                payService.PaySuccess(out_trade_no, 1);
            } else {
                log.error("挂牌支付回调失败");
            }
        } catch (Exception ex) {
            log.error("挂牌支付回调异常.");
            ex.printStackTrace();
        }
        return "SUCCESS";
    }

    @PostMapping(value = "/getPayUrl")
    public AjaxResult getPayUrl(@RequestBody PageData pd) {
        log.info("【开始发起微信支付,生成付款码】....");
        String url = null;
        try {
            //url = serverConfig.getUrl() + payService.getPayUrl(pd.get("contractId").toString(), pd.get("price").toString());
            url = "https://img.banquango.com" + payService.getPayUrl(pd.get("contractId").toString(), pd.get("price").toString());
        } catch (Exception ex) {
            log.error("【生成付款码失败】" + ex.getMessage());
            return AjaxResult.error("订单信息已失效,请重新发起支付.");
        }
        log.info("【微信付款二维码地址】：" + url);
        return AjaxResult.success("付款码已生成", url);
    }

    @PostMapping(value = "/getPayResult")
    public AjaxResult getPayResult(@RequestBody PageData pd) {
        log.info("【客户端轮询查询支付结果】....");
        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        if (loginUser == null) {
            return AjaxResult.error(401, "未登录");
        }
        boolean result = payService.payResult(pd.get("contractId").toString(), loginUser.getBqUser().getUserId().toString());
        return AjaxResult.success("支付成功", result);
    }


    /**
     * 获取用户openId
     */
    @PostMapping(value = "/getUserOpenId")
    public AjaxResult getUserOpenId(@RequestBody PageData pd) {
        // 授权（必填）
        String grant_type = "authorization_code";

        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        BqUser bqUser = loginUser.getBqUser();
        BqUser byUserId = bqUserService.findByUserId(bqUser.getUserId().toString());
        // 登录凭证不能为空
        if (pd.get("code") == null) {
            return AjaxResult.error(500, "code不能为空");
        }
        // 请求参数
        String params = "appid=" + WXpayConfig.APPID + "&secret=" + WXpayConfig.AppSecret + "&js_code=" + pd.get("code").toString() + "&grant_type="
                + grant_type;
        // 发送请求
        String sr = HttpUtils.sendGet("https://api.weixin.qq.com/sns/jscode2session", params);
        // 解析相应内容（转换成json对象）
        log.info("--------sr--------"+ sr);
        JSONObject json = JSONObject.fromObject(sr);
        // 用户的唯一标识（openid）
        String openid = (String) json.get("openid");
        log.info("--------openid--------" + openid);
        if (StringUtils.isNotNull(openid)){
            byUserId.setOpenId(openid);
            byUserId.setWechatState(1);
            bqUserService.submitEditData(byUserId);
        }
        return AjaxResult.success(200, "成功", openid);
    }

    /**
     * 查看用户是否绑定微信openid
     *
     * @return
     */
    @PostMapping(value = "/selectUserOpenId")
    public AjaxResult selectUserOpenId() {
        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        if (loginUser == null) {
            return AjaxResult.error(401, "未登录");
        }
        BqUser bqUser = loginUser.getBqUser();
        BqUser byUserId = bqUserService.findByUserId(bqUser.getUserId().toString());
        if (byUserId.getWechatState() == null || !byUserId.getWechatState().equals(1)) {
            return AjaxResult.success(200, "", false);
        }
        return AjaxResult.success(200, "", true);
    }

    /**
     * 小程序调起微信支付
     *
     * @param pd
     * @return
     */
    @PostMapping(value = "/getWxpay")
    public AjaxResult getWxpay(@RequestBody PageData pd) {
        Map<String, Object> wxPay;
        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        if (loginUser == null) {
            return AjaxResult.error(401, "未登录");
        }
        BqUser bqUser = loginUser.getBqUser();
        BqUser byUserId = bqUserService.findByUserId(bqUser.getUserId().toString());
        try {
            wxPay = payService.getWxPay(pd.get("contractId").toString(), pd.get("price").toString(), byUserId.getOpenId());
        } catch (Exception ex) {
            ex.printStackTrace();
            return AjaxResult.error("支付调起失败");
        }
        return AjaxResult.success(wxPay);
    }

    /**
     * pc调用支付宝支付
     *
     * @param pd
     * @return
     */
    @PostMapping(value = "/getAliPay")
    public String getAliPay(@RequestBody PageData pd){
        BqLoginUser loginUser = bqTokenService.getBqLoginUser(ServletUtils.getRequest());
        String url = null;
        if (loginUser == null) {
            throw new BaseException("未登录");
        }
        try {
           url  = payService.getAliPay(pd.get("contractId").toString(), pd.get("price").toString());
        } catch (Exception ex) {
            ex.printStackTrace();
            return "支付调起失败";
        }
        return url;
    }

    /**
     * 支付宝支付成功回调地址
     */
    @PostMapping(value = "/returnAliPaySucc")
    public String returnAliPaySucc(HttpServletRequest request) {
        log.info("【支付成功回调入口】");
        try {
            //支付宝回调处理
            //调用SDK验证签名
            Map<String, String> stringStringMap = WXPayUtil.convertRequestParamsToMap(request);
            log.info("支付宝回调,sign:{},trade_status:{},参数:{}",stringStringMap.get("sign"),stringStringMap.get("trade_status"),stringStringMap.toString());
            boolean signVerified = AlipaySignature.rsaCheckV1(stringStringMap, AlipayConfig.ALIPAY_PUBLIC_KEY,
                    AlipayConfig.charset, AlipayConfig.sign_type);
            if (signVerified) {
                log.info("支付宝回调签名认证成功");
                if(stringStringMap.get("trade_status").equals("TRADE_FINISHED") || stringStringMap.get("trade_status").equals("TRADE_SUCCESS")){
                    //处理自己系统的业务逻辑，如：将支付记录状态改为成功，需要返回一个字符串success告知支付宝服务器
                    //返回成功后修改订单状态
                    String out_trade_no = stringStringMap.get("out_trade_no");
                    payService.PaySuccess(out_trade_no, 2);
                } else {
                    //支付失败不处理业务逻辑
                    log.info("支付失败");
                }
            }else {
                //签名验证失败不处理业务逻辑
                log.info("签名验证失败");
            }
        } catch (Exception ex) {
            log.error("挂牌支付回调异常.");
            ex.printStackTrace();
        }
        return "SUCCESS";
    }
}
